package com.sunsharing.flow.model;

import com.sunsharing.flow.event.NodeEnterEvent;
import com.sunsharing.flow.event.NodeLeaveEvent;
import com.sunsharing.flow.exe.ExecutionContext;
import org.apache.log4j.Logger;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: criss
 * Date: 13-5-4
 * Time: 下午1:55
 * To change this template use File | Settings | File Templates.
 */
public class Node  extends GraphElement {

    /**日志**/
    transient protected Logger logger = Logger.getLogger(this.getClass());


    //离开的所有迁移
    protected List leavingTransitions = new ArrayList();

    transient Map leavingTransitionMap = null;

    //进入的所有迁移
    protected List arrivingTransitions = new ArrayList();


    //支持的事件类型
    public static final Class[] supportedEventTypes = new Class[] {
            NodeEnterEvent.class, NodeLeaveEvent.class
    };



    /**
     * 功能描述:
     *    返回的所有支持事件类型
     * @return String[]
     */
    public Class[] getSupportedEventTypes() {
        return supportedEventTypes;
    }


    public Node() {
    }



    /**
     * 功能描述:
     *    进入节点
     * @param executeContext ExecutionContext
     */
    public void enter(ExecutionContext executeContext) {

        NodeEnterEvent event = new NodeEnterEvent(executeContext);
        event.setEventSource(this);
        multicastEvent(event);
        logger.debug("进入节点:" + this);
        executeContext.setNode(this);
        //executeContext.setTransition(null);
        executeContext.getToken().setNode(this);

        execute(executeContext);
    }

    /**
     * 功能描述:
     *     执行节点
     */
    public void execute(ExecutionContext executeContext) {

    }


    /**
     * 功能描述:
     *    离开节点
     */
    public void leave(ExecutionContext executeContext) {
        leave(executeContext, this.getDefaultLeavingTransition());
    }


    /**
     * 功能描述:
     *     离开节点
     * @param executeContext ExecutionContext
     * @param transitionName String
     */
    public void leave(ExecutionContext executeContext, String transitionName) {

        logger.debug("Node.leave方法[选择离开的迁移为:" + transitionName + "]");
        //根据迁移名获得迁移
        Transition transition = this.getLeavingTransition(transitionName);

        //进入迁移
        leave(executeContext, transition);

    }


    /**
     * 功能节点:
     *    离开节点
     * @param executeContext ExecutionContext
     * @param transition Transition
     */
    public void leave(ExecutionContext executeContext, Transition transition) {

        if (transition == null) {
            throw new RuntimeException("没有指定离开迁移,节点无法离开!");
        }
        //节点离开事件
        NodeLeaveEvent event = new NodeLeaveEvent(executeContext);
        //设置事件源
        event.setEventSource(this);
        multicastEvent(event);


        //进入迁移
        transition.take(executeContext);

    }


    /**
     * 功能描述:
     *     回滚
     * @param node Node
     */
    public boolean rollback(ExecutionContext executeContext,Node node) {
        return false;

    }

    /**
     * 功能描述:
     *    撤消上一个动作
     * @param executeContext ExecutionContext
     * @return boolean
     */
    public void withdraw(ExecutionContext executeContext) {

    }



    /**
     * 功能描述:
     *    获得离开的所有迁移
     * @return List
     */
    public List getLeavingTransitions() {
        return leavingTransitions;
    }

    /**
     * 功能描述:
     *    获得默认的迁移
     * @return Transition
     */
    public Transition getDefaultLeavingTransition() {

        Transition defaultTransition = null;

        if ((leavingTransitions != null)
                && (leavingTransitions.size() > 0)) {
            defaultTransition = (Transition) leavingTransitions.get(0);
        }

        return defaultTransition;
    }


    /**
     * 功能描述:
     *     获得离开的迁移Map
     * @return Map
     */
    public Map getLeavingTransitionsMap() {

        if ((leavingTransitionMap == null || leavingTransitionMap.size() == 0) && (leavingTransitions != null)) {

            leavingTransitionMap = new HashMap();
            Iterator itor = leavingTransitions.iterator();
            while (itor.hasNext()) {
                Transition leavingTransition = (Transition) itor.next();
                leavingTransitionMap.put(leavingTransition.getName(),
                        leavingTransition);
            }
        }
        return leavingTransitionMap;
    }

    /**
     * 功能描述:
     *    增加离开迁移
     * @param leavingTransition Transition
     * @return Transition
     */
    public Transition addLeavingTransition(Transition leavingTransition) {

        if (leavingTransition == null) {
            throw new IllegalArgumentException(
                    "不允许为节点增加一个空的离开迁移");
        }
        if (leavingTransitions == null) {
            leavingTransitions = new ArrayList();
        }
        leavingTransitions.add(leavingTransition);
        leavingTransition.fromNode = this;
        leavingTransitionMap = null;
        return leavingTransition;
    }

    /**
     * 功能描述:
     *     移除所有的迁移
     */
    public void removeAllLeavingTransitions() {
        Iterator itor = this.getLeavingTransitions().iterator();
        while (itor.hasNext()) {
            Transition leavingTransition = (Transition) itor.next();
            leavingTransition.fromNode = null;
            leavingTransitionMap = null;
        }
        this.getLeavingTransitions().clear();
    }


    /**
     * 功能描述:
     *    移除离开迁移
     * @param leavingTransition Transition
     */
    public void removeLeavingTransition(Transition leavingTransition) {

        if (leavingTransition == null) {
            throw new IllegalArgumentException(
                    "不允许节点移除一个空的离开迁移");
        }

        if (leavingTransitions != null) {
            if (leavingTransitions.remove(leavingTransition)) {
                leavingTransition.fromNode = null;
                leavingTransitionMap = null;
            }
        }
    }

    /**
     * 功能描述:
     *    判断是否有离开迁移
     * @param transitionName String
     * @return boolean
     */
    public boolean hasLeavingTransition(String transitionName) {
        if (leavingTransitions == null) {
            return false;
        }
        return getLeavingTransitionsMap().containsKey(transitionName);
    }

    /**
     * 功能描述:
     *    根据迁移名称获得对应的迁移
     * @param transitionName String
     * @return Transition
     */
    public Transition getLeavingTransition(String transitionName) {

        Transition transition = null;
        if (leavingTransitions != null) {
            transition = (Transition) getLeavingTransitionsMap().get(
                    transitionName);
        }

        return transition;
    }

    public String getLeavingTransitionByExpresstion(String out) {
        if(out==null)
        {
            return null;
        }
        Transition transition = null;
        for(Iterator iter = leavingTransitions.iterator();iter.hasNext();)
        {
            Transition tr = (Transition)iter.next();
            if(out.equals(tr.getExpression()))
            {
                return tr.getId();
            }
        }

        return null;
    }




    /**
     * 功能描述:
     *    设置离开迁移
     * @param leavingTransitions List
     */
    public void setLeavingTransitions(List leavingTransitions) {
        this.leavingTransitions = leavingTransitions;
    }


    /**
     * 功能描述:
     *     判断是否包含指定名称的迁移
     * @param
     * @param name String
     * @return boolean
     */
    boolean containsName(String name) {

        Iterator iter = leavingTransitions.iterator();
        while (iter.hasNext()) {
            Transition transition = (Transition) iter.next();
            if ((name == null) && (transition.getName() == null)) {
                return true;
            } else if ((name != null) && (name.equals(transition.getName()))) {
                return true;
            }
        }
        return false;
    }


    /**
     * 功能描述:
     *     获得所有的离开迁移
     * @return List
     */
    public List getLeavingTransitionsList() {
        return leavingTransitions;
    }

    /**
     * 功能描述:
     *    获得所有的到达迁移
     * @return Set
     */
    public List getArrivingTransitions() {
        return arrivingTransitions;
    }

    /**
     * 功能描述:
     *     设置到达迁移
     * @param arrivingTransitions Set
     */
    public void setArrivingTransitions(List arrivingTransitions) {
        this.arrivingTransitions = arrivingTransitions;
    }



    /**
     * 功能描述:
     *    为节点增加到达迁移
     * @param arrivingTransition Transition
     * @return Transition
     */
    public Transition addArrivingTransition(Transition arrivingTransition) {
        if (arrivingTransition == null) {
            throw new IllegalArgumentException(
                    "不允许为节点增加一个空的到达迁移");
        }
        if (arrivingTransitions == null) {
            arrivingTransitions = new ArrayList();
        }
        arrivingTransitions.add(arrivingTransition);
        arrivingTransition.toNode = this;
        return arrivingTransition;
    }

    /**
     * 功能描述:
     *    移除到达迁移
     * @param arrivingTransition Transition
     */
    public void removeArrivingTransition(Transition arrivingTransition) {
        if (arrivingTransition == null) {
            throw new IllegalArgumentException(
                    "不允许节点移除一个空的到达迁移");
        }
        if (arrivingTransitions != null) {
            if (arrivingTransitions.remove(arrivingTransition)) {
                arrivingTransition.toNode = null;
            }
        }
    }


    /**
     * 功能描述:
     *     移除所有的到达迁移
     */
    public void removeAllArrivingTransitions() {

        Iterator itor = this.getArrivingTransitions().iterator();
        while (itor.hasNext()) {
            Transition arrivingTransition = (Transition) itor.next();
            arrivingTransition.toNode = null;
            if(arrivingTransition.fromNode!=null)
            {
                arrivingTransition.fromNode.removeLeavingTransition(
                        arrivingTransition);
            }
        }

        this.getArrivingTransitions().clear();

    }




    /**
     * 功能描述:
     *     获得该节点的上一节点集合
     * @return Set
     */
    public Set getPreviousNodes() {
        Set previousNodes = new HashSet();

        //获得该节点的所有到达迁移
        List transitions = this.getArrivingTransitions();
        Iterator tranItor = transitions.iterator();
        while (tranItor.hasNext()) {
            Transition transition = (Transition) tranItor.next();
            Node node = transition.getFromNode();
            previousNodes.add(node);
        }

        return previousNodes;

    }









    public String toString() {
//        return ToStringBuilder.reflectionToString(this,
//                ToStringStyle.
//                        MULTI_LINE_STYLE, false,
//                this.getClass());
        return this.id;
    }


    public static void main(String[] args) {

    }


}
